﻿using System;
using System.Threading;
using WeDonekRpc.IOSendInterface;

namespace WeDonekRpc.PipeServer.Model
{
    internal class Page : ICloneable
    {
        private static readonly byte _SingleDataPage = ConstDicConfig.DataPageType + ConstDicConfig.SinglePagType;
        private static uint _PageId = 1;

        private static uint _GetPageId ()
        {
            return Interlocked.Increment(ref _PageId);
        }

        public static Page GetSysPage (string type, string str)
        {
            return new Page
            {
                PageType = ConstDicConfig.SystemPageType,
                SendData = str,
                SendType = ConstDicConfig.StringSendType,
                Type = type
            };
        }


        public static Page GetDataPage (string pipeName, Guid clientId, string type, int timeOut, int syncTimeOut)
        {
            return new Page
            {
                PipeName = pipeName,
                ClientId = clientId,
                PageType = ConstDicConfig.DataPageType,
                PageId = _GetPageId(),
                SendData = Array.Empty<byte>(),
                SendType = ConstDicConfig.StreamSendType,
                Type = type,
                TimeOut = timeOut,
                SyncTimeOut = syncTimeOut
            };
        }
        public static Page GetDataPage<T> (string pipeName, Guid clientId, string type, T data, int timeOut, int syncTimeOut)
        {
            return new Page
            {
                PipeName = pipeName,
                ClientId = clientId,
                PageType = ConstDicConfig.DataPageType,
                PageId = _GetPageId(),
                SendData = data,
                SendType = ConstDicConfig.ObjectSendType,
                Type = type,
                TimeOut = timeOut,
                SyncTimeOut = syncTimeOut
            };
        }

        public static Page GetSingleDataPage (string pipeName, Guid clientId, string type, int timeOut, int syncTimeOut)
        {
            return new Page
            {
                PipeName = pipeName,
                ClientId = clientId,
                PageType = _SingleDataPage,
                PageId = uint.MinValue,
                SendData = Array.Empty<byte>(),
                SendType = ConstDicConfig.StreamSendType,
                Type = type,
                TimeOut = timeOut,
                SyncTimeOut = syncTimeOut
            };
        }
        public static Page GetSingleDataPage<T> (string pipeName, Guid clientId, string type, T data, int timeOut, int syncTimeOut)
        {
            return new Page
            {
                ClientId = clientId,
                PipeName = pipeName,
                PageType = _SingleDataPage,
                PageId = uint.MinValue,
                SendData = data,
                SendType = ConstDicConfig.ObjectSendType,
                Type = type,
                TimeOut = timeOut,
                SyncTimeOut = syncTimeOut
            };
        }
        public static Page GetBatchDataPage<T> (string type, T data, int timeOut, int syncTimeOut)
        {
            return new Page
            {
                PageType = _SingleDataPage,
                SendData = data,
                PageId = uint.MinValue,
                SendType = ConstDicConfig.ObjectSendType,
                Type = type,
                TimeOut = timeOut,
                SyncTimeOut = syncTimeOut
            };
        }
        public static Page GetReply (GetDataPage arg, object data)
        {
            return new Page
            {
                SendData = data,
                SendType = ToolsHelper.GetSendType(data.GetType()),
                Type = arg.Type,
                PageType = ConstDicConfig.ReplyPageType,
                PageId = arg.PageId,
            };
        }
        public static ReplyPage GetReplyPage (GetDataPage arg, object data)
        {
            return new ReplyPage
            {
                Client = arg.Client,
                Page = new Page
                {
                    SendData = data,
                    SendType = ToolsHelper.GetSendType(data.GetType()),
                    Type = arg.Type,
                    PageType = arg.PageType == ConstDicConfig.SystemPageType ? arg.PageType : ConstDicConfig.ReplyPageType,
                    PageId = arg.PageId,
                },
                PageId = _GetPageId()
            };
        }

        public Guid? ClientId;
        public string PipeName;
        /// <summary>
        /// 父ID
        /// </summary>
        internal uint PageId;
        /// <summary>
        /// 需要发送的数据
        /// </summary>
        internal object SendData;
        /// <summary>
        /// 类型
        /// </summary>
        internal string Type;

        /// <summary>
        /// DataPageType的类型
        /// </summary>
        internal byte PageType;

        /// <summary>
        /// 发送的类型
        /// </summary>
        internal byte SendType;
        public int TimeOut;
        public int SyncTimeOut;

        public object Clone ()
        {
            return this.MemberwiseClone();
        }
    }
}
